home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Pascal / Book Demos in Pascal / SpriteEngine / SpriteEngine.p < prev    next >
Text File  |  1995-04-04  |  6KB  |  215 lines

  1. program SpriteEngine;
  2.  
  3.     uses
  4. {$IFC UNDEFINED THINK_PASCAL}
  5.         Types, QuickDraw, Fonts, Events, Packages, Menus, Dialogs, Windows,{}
  6.         OSUtils, ToolUtils, OSEvents, Resources, 
  7. {$ENDC}
  8.         QDOffScreen, SpriteStructure, SpriteTools, SpriteHandlers;
  9.  
  10. {SpriteEngine}
  11. {============}
  12.  
  13. {This demo sprite engine is designed for the following structure:}
  14. {(Lower units use the higher ones.)}
  15. {}
  16. {SpriteTools.c: Utilities for loading and drawing}
  17. {|}
  18. {SpriteHanders.c: All custom code: Sprite init, movement, collisions}
  19. {|}
  20. {SpriteEngine.c: Main program, sprite engine}
  21.  
  22. {The only files you need to edit in order to change the sprite behavior are}
  23. {the files SpriteHandlers.c and SpriteHandlers.h.}
  24.  
  25.  
  26. (* The actual sprite engine *)
  27.  
  28.  
  29.     procedure InitSpriteEngine (var offBounds: Rect; backgroundPictureID: Integer);
  30.  
  31.         var
  32.             backgroundPicture: PicHandle;
  33.             saveGD: GDHandle;
  34.             savePort: GWorldPtr;
  35.  
  36.     begin
  37.         MyNewGWorld(gOffScreen, offBounds);
  38.         MyNewGWorld(gBackScreen, offBounds);
  39.  
  40.         GetGWorld(savePort, saveGD);            (*Save the port/device*)
  41.         SetGWorld(GWorldPtr(gBackScreen), nil);
  42.  
  43.         EraseRect(offBounds);
  44.  
  45.         backgroundPicture := GetPicture(backgroundPictureID);
  46.         if (backgroundPicture <> nil) then
  47.  
  48.             begin
  49.                 DrawPicture(backgroundPicture, offBounds);
  50.                 ReleaseResource(Handle(backgroundPicture));
  51.             end;
  52.         SetGWorld(GWorldPtr(gOffScreen), nil);
  53.         CopyBits(gBackScreen^.portBits, gOffScreen^.portBits, offBounds, offBounds, srcCopy, nil);
  54.         SetGWorld(GWorldPtr(myWindow), GetMainDevice);
  55.         CopyBits(gOffScreen^.portBits, myWindow^.portBits, offBounds, offBounds, srcCopy, nil);
  56.         SetGWorld(savePort, saveGD);
  57.     end; (*InitSpriteEngine*)
  58.  
  59.  
  60.  
  61.     procedure RunSpriteEngine;
  62.  
  63.         const
  64.             kWallBounce = 7;(*1/10-ths of speed kept after wallbounce*)
  65.             kBallDiameterSquared = (32 * 32);(*Diameter 32, squared*)
  66.  
  67.         var
  68.             tmpRect: Rect;
  69.             saveGD: GDHandle;
  70.             savePort: GWorldPtr;
  71.             theSprite, anotherSprite: SpritePtr;
  72.             bounds1, bounds2: Rect;
  73.  
  74.     begin
  75.         GetGWorld(savePort, saveGD);                (*Save the port/device*)
  76. (*1: Erase all sprites from gOffScreen*)
  77. (*Note: We keep the rectangles for erasing on the screen, later.*)
  78.         SetGWorld(GWorldPtr(gOffScreen), nil);
  79.  
  80.         theSprite := gSpriteList;
  81.         while (theSprite <> nil) do
  82.             begin
  83.                 theSprite^.drawingRect := theSprite^.face^.portRect;
  84.                 OffsetRect(theSprite^.drawingRect, theSprite^.position.h, theSprite^.position.v);
  85.                 CopyBits(gBackScreen^.portBits, gOffScreen^.portBits, theSprite^.drawingRect, theSprite^.drawingRect, srcCopy, nil);
  86.  
  87.                 theSprite := theSprite^.next;
  88.             end;
  89.  
  90. (*2: Change the position and speed*)
  91.         theSprite := gSpriteList;
  92.         while (theSprite <> nil) do
  93.  
  94.             begin
  95.                 MoveSprite(theSprite);
  96.  
  97.                 theSprite := theSprite^.next;
  98.             end;(*position/speed loop*)
  99.  
  100. (*3: Check for collisions*)
  101.         theSprite := gSpriteList;
  102.         while (theSprite <> nil) do    (*For all sprites in the list…*)
  103.             begin
  104.                 bounds1 := theSprite^.face^.portRect;
  105.                 OffsetRect(bounds1, theSprite^.position.h, theSprite^.position.v);
  106.  
  107.                 anotherSprite := theSprite^.next;
  108.                 while (anotherSprite <> nil) do
  109.         (*compare its position to all following sprites*)
  110.                     begin
  111.                         bounds2 := anotherSprite^.face^.portRect;
  112.                         OffsetRect(bounds2, anotherSprite^.position.h, anotherSprite^.position.v);
  113.  
  114.                         if (SectRect(bounds1, bounds2, tmpRect)) then
  115.                             HitSprite(theSprite, anotherSprite);
  116.  
  117.                         anotherSprite := anotherSprite^.next;
  118.                     end;
  119.                 theSprite := theSprite^.next;
  120.             end; (*collision loop*)
  121.  
  122. (*4: Draw sprites in gOffScreen*)
  123. (*Note: PlotCIcon or DrawPicture are not very fast! We can speed it up my*)
  124. (*pre-drawing them in some offscreen, and CopyBits them from there.*)
  125.         theSprite := gSpriteList;
  126.         while (theSprite <> nil) do    (*For all sprites in the list…*)
  127.             begin
  128.                 tmpRect := theSprite^.face^.portRect;
  129.                 OffsetRect(tmpRect, theSprite^.position.h, theSprite^.position.v);
  130.                 PlotFace(theSprite^.face, gOffScreen, tmpRect.topLeft);
  131.                 theSprite := theSprite^.next;
  132.             end;
  133.  
  134. (*5: Copy sprites to the screen (gWind) - both old and new position!*)
  135. (*Note: Depending on what limitations we have on movement, we may be able to avoid the multiple*)
  136. (*CopyBitsing here. E.g. if sprites always move a maximum of 2 pixels, we can copy a 2 pixels*)
  137. (*larger area, etc.*)
  138.         SetGWorld(GWorldPtr(myWindow), saveGD);
  139.         theSprite := gSpriteList;
  140.         while (theSprite <> nil) do    (*For all sprites in the list…*)
  141.             begin
  142.                 CopyBits(gOffScreen^.portBits, myWindow^.portBits, theSprite^.drawingRect, theSprite^.drawingRect, srcCopy, nil);
  143.                 theSprite^.drawingRect := theSprite^.face^.portRect;
  144.                 OffsetRect(theSprite^.drawingRect, theSprite^.position.h, theSprite^.position.v);
  145.                 CopyBits(gOffScreen^.portBits, myWindow^.portBits, theSprite^.drawingRect, theSprite^.drawingRect, srcCopy, nil);
  146.  
  147.                 theSprite := theSprite^.next;
  148.             end;
  149.         SetGWorld(savePort, saveGD);
  150.     end; (*RunSpriteEngine*)
  151.  
  152.  
  153.  
  154. (* Standard inits *)
  155.  
  156.     procedure InitToolbox;
  157.     begin
  158. {$IFC UNDEFINED THINK_PASCAL}
  159.         InitGraf(@qd.thePort);
  160.         InitFonts;
  161.         FlushEvents(everyEvent, 0);
  162.         InitWindows;
  163.         InitMenus;
  164.         TEInit;
  165.         InitDialogs(nil);
  166. {$ENDC}
  167.         InitCursor;
  168.     end; (*InitToolbox*)
  169.  
  170.  
  171. (* Initialize - create window, load graphics *)
  172.  
  173.     procedure InitStuff;
  174.         var
  175.             windowRectangle: Rect;
  176.  
  177. (*Set up the window*)
  178.     begin
  179.         SetRect(windowRectangle, 50, 50, 450, 350);
  180.         myWindow := NewCWindow(nil, windowRectangle, 'Sprite test', true, documentProc, WindowPtr(-1), false, 0);
  181.         SetPort(myWindow);
  182.  
  183. {$IFC UNDEFINED THINK_PASCAL}
  184.         qd.randSeed := TickCount;    (*Seed the random number generator*)
  185. {$ELSEC}
  186.         randSeed := TickCount;    (*Seed the random number generator*)
  187. {$ENDC}
  188.     end; (*InitStuff*)
  189.  
  190.     const
  191.         kBackgroundPictureID = 128;
  192.  
  193. (* Main program *)
  194.  
  195.     var
  196.         startTime: LongInt;
  197.  
  198. begin
  199.     InitToolbox;
  200.     InitStuff;
  201.     InitSpriteEngine(myWindow^.portRect, kBackgroundPictureID);
  202.     InitSprites;
  203.  
  204. {HideCursor;}
  205.     while not Button do
  206.         begin
  207.             startTime := TickCount;
  208.             RunSpriteEngine;
  209.             while TickCount < startTime + kFrameTime do
  210.                 ;
  211.         end;
  212. {ShowCursor;}
  213.  
  214.     FlushEvents(mDownMask, 0);
  215. end. (*main*)